﻿using Open.Nat;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace DXApplication1
{
    public partial class Form1 : DevExpress.XtraEditors.XtraForm
    {
        public static Thread StartupProcedures;

        public static Form1 _main;
        public Form1()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();

            _main = this;



        }

        private async static Task Test()
        {
            var nat = new NatDiscoverer();
            var cts = new CancellationTokenSource(5000);
            var device = await nat.DiscoverDeviceAsync(PortMapper.Upnp, cts);

            var sb = new StringBuilder();
            var ip = await device.GetExternalIPAsync();

            sb.AppendFormat("\nYour IP: {0}", ip);
            await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1600, 1700, "Open.Nat (temporary)"));
            await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1601, 1701, "Open.Nat (Session lifetime)"));
            await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1602, 1702, 0, "Open.Nat (Permanent lifetime)"));
            await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1603, 1703, 20, "Open.Nat (Manual lifetime)"));
            sb.AppendFormat("\nAdded mapping: {0}:1700 -> 127.0.0.1:1600\n", ip);
            sb.AppendFormat("\n+------+-------------------------------+--------------------------------+------------------------------------+-------------------------+");
            sb.AppendFormat("\n| PROT | PUBLIC (Reacheable)           | PRIVATE (Your computer)        | Descriptopn                        |                         |");
            sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
            sb.AppendFormat("\n|      | IP Address           | Port   | IP Address            | Port   |                                    | Expires                 |");
            sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
            foreach (var mapping in await device.GetAllMappingsAsync())
            {
                sb.AppendFormat("\n|  {5} | {0,-20} | {1,6} | {2,-21} | {3,6} | {4,-35}|{6,25}|",
                    ip, mapping.PublicPort, mapping.PrivateIP, mapping.PrivatePort, mapping.Description, mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP", mapping.Expiration.ToLocalTime());
            }
            sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");

            sb.AppendFormat("\n[Removing TCP mapping] {0}:1700 -> 127.0.0.1:1600", ip);
            await device.DeletePortMapAsync(new Mapping(Protocol.Tcp, 1600, 1700));
            sb.AppendFormat("\n[Done]");


            _main.memoEdit1.Text += (sb.ToString());
            /*
                            var mappings = await device.GetAllMappingsAsync();
                            var deleted = mappings.All(x => x.Description != "Open.Nat Testing");
                            Console.WriteLine(deleted
                                ? "[SUCCESS]: Test mapping effectively removed ;)"
                                : "[FAILURE]: Test mapping wan not removed!");
            */
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
            //Process.Start(@"C:\Users\Roger Jenkins\Downloads\Open.NAT-master\Open.NAT-master\Open.Nat.ConsoleTest\bin\Debug\Open.Nat.ConsoleTest.exe");
        }

        private void simpleButton1_Click(object sender, EventArgs e)
        {
            NatDiscoverer.TraceSource.Switch.Level = SourceLevels.Verbose;
            NatDiscoverer.TraceSource.Listeners.Add(new ColorConsoleTraceListener());
            Test().Wait();

            Console.WriteLine("");
            Console.WriteLine("Socket listening on port 1602. Remember, it is mapped to external port 1702!!!");
            Console.WriteLine("Test it with http://www.canyouseeme.org/ online tool");

            var endPoint = new IPEndPoint(IPAddress.Any, 1602);
            var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            socket.SetIPProtectionLevel(IPProtectionLevel.Unrestricted);
            socket.Bind(endPoint);
            socket.Listen(4);

            //Console.WriteLine("Press any key to exit...");
            //Console.ReadKey();
            //socket.Close();
        }

    }
}
